package edu.pku.sei.transformation.editor.controller.commands.node;

import java.util.List;

import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.jface.dialogs.MessageDialog;

import edu.pku.sei.modeler.model.core.MetaModel;
import edu.pku.sei.modeler.model.core.MetaModelElement;
import edu.pku.sei.modeler.model.core.MetaPackage;
import edu.pku.sei.modeler.model.structure.MetaDiagram;
import edu.pku.sei.modeler.model.structure.MetaNode;

public class NodeCreateCommand extends NestedCommand {
	protected Rectangle bounds;

	protected MetaNode node;

	protected MetaDiagram diagram;

	protected MetaNode parent;

	// private boolean packageSet, packageAdded;

	public NodeCreateCommand(MetaNode newObject, MetaDiagram parent,
			Rectangle bounds) {
		super("Create Node");
		node = newObject;
		diagram = parent;
		this.bounds = bounds;
	}

	public boolean canExecute() {
		if (super.canExecute()) {
			return node != null && diagram != null && bounds != null;
		} else {
			return false;
		}
	}

	public void execute() {
		if (alreadyOnDiagram(node, diagram)) {
			MessageDialog.openWarning(null, "warning", "The element:"
					+ node.getModelElement() + " is already on the diagram!");
			return;
		}
		node.setLocationX(bounds.getLocation().x);
		node.setLocationY(bounds.getLocation().y);
		node.setWidth(bounds.width);
		node.setHeight(bounds.height);
		node.setDiagram(diagram);
		// node.setModel(diagram.getModel());
		diagram.getNodes().add(node);

		if (parent != null) {
			parent.addToManager(node);
		}
		if (modelCmd != null)
			modelCmd.execute();
	}

	protected MetaPackage findPackage(MetaModel model, MetaDiagram diagram) {
		if (model == null || diagram == null)
			return null;
		List pkgs = model.getPackages();
		for (int i = 0; i < pkgs.size(); i++) {
			MetaPackage pkg = (MetaPackage) pkgs.get(i);
			MetaPackage result = findPackage(pkg, diagram);
			if (result != null)
				return result;
		}
		return null;
	}

	protected MetaPackage findPackage(MetaPackage pkg, MetaDiagram diagram) {
		if (pkg == null)
			return null;
		List diags = pkg.getDiagrams();
		for (int i = 0; i < diags.size(); i++) {
			if (diags.get(i) == diagram)
				return pkg;
		}
		List pkgs = pkg.getSubPackages();
		for (int i = 0; i < pkgs.size(); i++) {
			MetaPackage subPkg = (MetaPackage) pkgs.get(i);
			MetaPackage result = findPackage(subPkg, diagram);
			if (result != null)
				return result;
		}
		return null;
	}

	/**
	 * for checking Drag & Drop
	 * 
	 * @param node
	 * @param diagram
	 * @return
	 */
	protected boolean alreadyOnDiagram(MetaNode node, MetaDiagram diagram) {
		List<MetaNode> nodes = diagram.getNodes();
		for (MetaNode n : nodes) {
			if (n.getModelElement() == node.getModelElement())
				return true;
		}
		return false;
	}

	protected boolean alreadyOnDiagram(MetaModelElement element,
			MetaDiagram diagram) {
		List<MetaNode> nodes = diagram.getNodes();
		for (MetaNode n : nodes) {
			if (n.getModelElement() == element)
				return true;
		}
		return false;
	}

	public MetaNode getParent() {
		return parent;
	}

	public void setParent(MetaNode parent) {
		this.parent = parent;
	}

	public void undo() {
		diagram.getNodes().remove(this.node);
		if (modelCmd != null) {
			modelCmd.undo();
		}
	}
}
